查看原文
其他

自研虚拟偶像文件的制作与使用

刘宏伟 哔哩哔哩技术 2024-02-26

本期作者


刘宏伟

哔哩哔哩资深开发工程师

负责主站直播中心的虚拟产品开发,专注于虚拟基础能力的建设。


01 自研格式背景


目前最适合作为通用跨平台角色模型中, VRM是最适合作为虚拟开播或者社交游戏的3D载体,而互联网上资源存量最大的MMD,由于历史久远,作为早期生产卡通渲染视频工具的副产物,并没有提供对面捕和动作捕捉做适配,且渲染技术落后,于是有了日本多家企业联合推出的一种“VRM”是用于处理VR应用程序的Avatar模型数据的文件格式。

实际上,VRM也确实能够满足当前普通虚拟主播的开播或者社交类的使用场景,所以在决定开启该项目以来,也一直备受质疑,遇到很多的阻力,其中最大的质疑声便是VRM已经有丰富的资源和工具链完善了,再做类似的事情推一个新标准将会面临更大的困难难以推广开来,但是我觉得在最开始,这样的付出是值得的,并且VRM在诞生之初也存在这类问题,目前的版本下的VRM能满足基础的虚拟开播或者社交类游戏加载角色的需求,无法满足场景加载和更丰富的交互需求,渲染支持也比较单一,更重要的是缺乏对第三方应用的扩展支持能力,在元宇宙,UGC等概念开始普及开来,用户创作成为不可阻挡的趋势下,除了做好用户创作的扶持,对开发者和开源社区的支持将是衡量一个标准的行业影响力的重要指标。


02 接入BVA开发者能收获什么


技术上,该文件格式可以存储任意类型的信息,比如多媒体,动画片段,自定义数据,在未来还会加入lua或者js这类热更新引擎用于更好的支持用户创作复杂的交互世界。目前可以在直播开播中作为开播资源的文件,游戏或者社交应用的avatar,尤其是VR类应用,还有像虚拟会议等需要化身的场景,以及可以基于这个开发类似MMD的制作虚拟人视频的工具,虚拟偶像等,跟虚拟场景和用户内容生成相关的都可以集成到应用中使用,对于个人开发者而言,它能很方便的在已有的MMD,VRM模型的基础上添加一些功能进行导出,并支持场景的导出,因为它做到了以下几点:

  • 统一角色模型的规范,提供对面部捕捉,动作捕捉更好的适配规范,并且该规范也适用于VR游戏等需要Avatar的应用场景。

  • 支持更多更为复杂的材质类型,覆盖了PBR和卡通渲染,并提供了代码生成工具,可以很方便的生成自定义着色器的导入导出代码。

  • 一个文件即可提供运镜,动作,角色换装,场景,灯光,多媒体等数据支持,无需额外附加文件,并且该文件的使用是跨系统,跨平台,也不用依赖特定的引擎版本。

  • 自带一套效率非常高支持并行运算的动态骨骼物理系统,用于模拟布料头发。

  • 提供功能扩展的代码生成工具,在支持内置了功能性组件的序列化基础上,第三方也可很快的完成特定组件的支持。


BVA格式的Unity SDK已经开源,我们希望能在未来一年内看到很多与之相关的工具被开发出来,也有第三方应用商和虚拟偶像爱好者参与进来,Bilibili旗下的虚拟业务会跟进落地,在各种应用上与大家见面。


03 与VRM的功能对比



04 人物角色制作导出


前提:一个导入Unity后可以被正确识别出Humanoid Avatar的人物模型。

通常要配置一个模型为标准的BVA角色模型需要进行以下的工作:

配置物理,BVA使用基于骨骼的动态物理:


修改材质为BVA内置的标准材质,目前支持以下类型的Shader:

  • Lit

  • Complex Lit

  • Unlit

  • Skybox

  • UTS2

  • LiliumToonGraph

  • MToon(URP版本)

  • ZeldaToon

  • ToonLit(带卡通效果的Lit)


添加面捕支持:

这一步不是必须,但是为了能满足快速接入面捕,通常添加一个BlendshapeMixer脚本,以便您的面捕相关的应用可以快速从VRM迁移。如果您使用ARKit的面部标准制作的模型,那可以直接导出。BlendshapeMixer现阶段作为一个面捕数据桥接的组件使用,其与VRM的规范一致,未来会考虑进行移除。

对于自定义Shader,我们实现了一个代码生成工具,所以你可以选择你想要导出的Shader参数,然后生成代码来支持导出后导入使用。

重要事项:所有的自定义Shader都会添加一个 `KHR_materials_unlitExtension` 扩展到材质下。


为了兼容标准的gltf参数,使用这些参数的材质将会导出为标准的GLTF材质参数。

对于自定义Shader,我们实现了一个代码生成工具,所以你可以选择你想要导出的Shader参数,然后生成代码来支持导出后导入使用。

  • 所有的自定义Shader都会添加一个 KHR_materials_unlitExtension 扩展到材质下。

为了兼容标准的gltf参数,使用这些参数的材质将会导出为标准的GLTF材质参数。


  • NormalMap 必须遵循以下命名规范,因为 Unpack 的一个操作需要在导出前执行。可以在这里查看NormalMap的详细信息 https://docs.unity3d.com/Manual/StandardShaderMaterialParameterNormalMap.html

  • 为了减少Shader的变体,强烈推荐你只使用 Exponential Squared 作为唯一的雾模式。


05 VRM模型转化


VRM模型在拖拽导入后即可直接进行导出,加载的时候会自动的将需要的面捕,物理等配置完成转化并保存相应的组件到模型上,材质MToon不变,但是会换成Universal RP的着色器,导入后的模型可以直接导出。


06 MMD模型转化


由于MMD模型的主体和头部以及所有顶点都在网格上,因此头部的Blendshape将影响所有顶点,这可能会导致输出文件的体积变得非常的大,会严重影响导出和加载的效率。

因此,在导出MMD之前,将分离受混合形状影响的顶点以形成子网格。这大大减少了导出文件的大小,以达到与MMD文件本身的大小相当。

  • 本质上, 任何人物模型带有一个有效的 Humanoid Avatar 都可以被导出为角色模型。

MMD在互联网上拥有最多的存量,在这个教程里,我们将导入被广泛熟悉的PMX文件(MMD模型), 然后再导出这个角色模型为BVA格式。


步骤:

    1. 创建一个文件夹, 名称叫做 "ImportScene" 在Assets里。

    2. 把PMX还有相关的文件到Assets/ImportScene这个文件夹。


    3. 经过一段时间的处理后, 一个Prefab文件夹将会被创建, 并且一个和PMX文件相同名称的预制体将会创建。


    4. 从菜单打开 BVA/Export/Export Avatar


    5. 将预制体放到那上面进行赋值, 两个错误将会显现,点击 Fix 以修复这些错误。


    6. 将 Export AudioClip 勾选, 这里我想导出两个音频片段。


    7. 点击预制体,你将会觉察到两个组件已经添加到物体上,如果你直接在场景中拖拽物体,该组件也是会被添加的,填充这些内容以便达到目的。


    8. 添加 Export 按钮然后选择你想要保存的文件夹。


解释:

  • BlendshapeMixer 组件让面捕捕捉与脸部的网格BlendShape做一个桥接。

  • BVAMetaInfo 组件包含一些元数据,但是对功能无任何影响。


07 场景导出


为了详细的向大家解释一下BVA的导入导出的工作流程,以下演示了导入从互联网上下载获取的gltf资源到工程里,配置后输出为BVA的场景文件。

    1. 从Sketchfab上下载一个房间的模型和一个打碟器的模型


    2. 解压下载的文件,将模型的整个文件夹拖进Unity的资源栏里


        等待一会处理完就会生成导入后的资源


        并且可以在右边看到Preview视图,此时可以像FBX那样直接将文件拖进场景,Unity会当成Prefab处理


    3. 新建一个空场景,添加灯光和相机,在房间里添加两个Area Light拖到合适的大小,上下方向上都各放置一个,并放置两个Spot Light,将两盏灯光的材质设置为自发光并设置为Baked Global Illumination,这样就设置好了所有的烘焙光


    4. 调整下房间的整体缩放,并将物体全部拖出来放到根目录下,这样导出的场景,能在加载的时候一个一个显示出来,让加载过程看起来更有连贯性


    5. 将房间里的所有物体并设置为静态,并设置物体的层级为BVA Scene Static(Lightmap),这个层级用于烘焙静态物体


    6. 打开Lighting设置面板,取消勾选Realtime Global Illumination,选择勾选Backed Global Illumination,设置各项烘焙参数后点击Generate Lighting烘焙场景,等待几分钟完成烘焙


    7. 添加一个Directional Light,设置为Realtime实时光,并设置Culling Mask为BVA Scene Realtime,然后将打碟器拖进场景中,设置Layer为BVA Scene Realtime,这样只有这个打碟器会受到这个实时光的影响


    8. 最后添加一个后处理,在Hierarchy右键选择Volume/Global Volume。然后添加Bloom和Tonemapping,并勾选Camera的Post Processing。


    9. 打开导出面板,通过菜单栏BVA/Export/Export Scene打开导出的面板,选择Export Single Scene,点击勾选export original texture,这样尽可能的导出原图片提高导出的质量,再勾选导出RenderSetting和Lightmap导出这个场景,一般的只有用到了烘焙的场景才需要勾选这两项


    10. 输出的文件可以在各种Sample打包出来的应用里加载,点击下图查看在移动端的加载情况


08 运行时加载


加载方式上主要有如下两类:

  • 为Avatar专门写的多线程快速加载更多适用于较小的文件体积,加载的时候会卡主线程,大场景会有明显的卡顿和Crash风险(长时间不响应系统可能会自动结束进程)并且加载的东西会有一些限制,比如天空盒,渲染设置之类的就不会去加载,适合去加载角色模型和一些场景中的小物件。

  • 为了兼顾大场景渐进加载并减少内存占用,提供一种Payload机制,只在需要的某个资源的时候才开始加载该资源,采取Recursively Load(递归式加载)的方式加载,该方式会以单线程的方式去加载用到的资源,但是加载采用异步的Task方法会自动对任务进行切分,不会卡住渲染的主线程,适用于大场景加载,场景的根节点下的物体会依次显示出来,所以在导出场景的时候根据需要做一下根节点的。

BVA文件在导出的时候会针对不同的导出方式,添加一个Generator的标志,用以区分是Avatar还是Scene,如果是Avatar则会自动采取快速加载的方式。


工程源码的Sample示例里有加载场景和人物模型的相关示例。


https://github.com/bilibili/UnityBVA/tree/main/Assets/Samples




往期回顾:哔哩哔哩自研虚拟偶像文件格式BVA已开源!


继续滑动看下一个

自研虚拟偶像文件的制作与使用

刘宏伟 哔哩哔哩技术
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存